import sys
import psutil
import platform
import time
import threading
from datetime import datetime
import sqlite3
import os

from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout, QHBoxLayout,
    QLabel, QPushButton, QTreeView, QLineEdit, QSplitter, QStatusBar, QMenu,
    QMessageBox, QDialog, QTextEdit, QHeaderView, QScrollArea, QFrame
)
from PyQt5.QtGui import (
    QFont, QColor, QBrush, QIcon, QPainter, QPen, QLinearGradient,
    QPainterPath, QFontDatabase, QStandardItemModel, QStandardItem
)
from PyQt5.QtWidgets import QAction
from PyQt5.QtCore import (
    Qt, QTimer, QThread, pyqtSignal, QPoint, QSize, QRectF, QEvent, QItemSelectionModel
)
# test of commit
# 尝试导入win32相关库，用于获取窗口信息
try:
    import win32gui
    import win32process
    WIN32_AVAILABLE = True
except ImportError:
    WIN32_AVAILABLE = False

class PerformanceMonitorThread(QThread):
    """性能监控线程，用于更新CPU和内存数据"""
    update_cpu_signal = pyqtSignal(float, list)
    update_memory_signal = pyqtSignal(float, float, float, list)
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.running = True
        self.cpu_history = []
        self.memory_history = []
        self.history_size = 100
    
    def run(self):
        while self.running:
            # 获取CPU使用率
            cpu_percent = psutil.cpu_percent(interval=0.1)
            self.cpu_history.append(cpu_percent)
            if len(self.cpu_history) > self.history_size:
                self.cpu_history.pop(0)
            
            # 获取内存信息
            memory = psutil.virtual_memory()
            self.memory_history.append(memory.percent)
            if len(self.memory_history) > self.history_size:
                self.memory_history.pop(0)
            
            # 发送信号
            self.update_cpu_signal.emit(cpu_percent, self.cpu_history.copy())
            self.update_memory_signal.emit(
                memory.percent,
                memory.total / (1024**3),
                memory.used / (1024**3),
                self.memory_history.copy()
            )
            
            time.sleep(1)
    
    def stop(self):
        self.running = False
        self.wait()

class ProcessUpdaterThread(QThread):
    """进程更新线程"""
    update_signal = pyqtSignal(list)
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.running = True
        self.parent = parent
    
    def run(self):
        """运行线程"""
        while self.running:
            try:
                processes = []
                # 获取封禁进程列表
                banned_processes = []
                if hasattr(self.parent, 'get_banned_processes'):
                    banned_processes = self.parent.get_banned_processes()
                
                # 获取所有进程
                for proc in psutil.process_iter([
                    'pid', 'name', 'cpu_percent', 'memory_percent', 
                    'status', 'num_threads', 'create_time', 'exe'
                ]):
                    try:
                        proc_info = proc.info
                        proc_name = proc_info['name']
                        proc_pid = proc_info['pid']
                        
                        # 检查是否为封禁进程
                        is_banned = False
                        for banned_name, add_time, block_count in banned_processes:
                            if proc_name.lower() == banned_name.lower():
                                try:
                                    # 尝试终止进程
                                    proc.terminate()
                                    try:
                                        proc.wait(timeout=1)
                                    except psutil.TimeoutExpired:
                                        try:
                                            proc.kill()
                                        except:
                                            pass
                                    # 更新拦截次数
                                    if hasattr(self.parent, 'increment_block_count'):
                                        self.parent.increment_block_count(banned_name)
                                except:
                                    pass
                                is_banned = True
                                break
                        
                        if is_banned:
                            continue
                        
                        # 获取创建时间
                        create_time = datetime.fromtimestamp(
                            proc_info['create_time']
                        ).strftime('%Y-%m-%d %H:%M:%S')
                        
                        processes.append((
                            proc_info['pid'],
                            proc_info['name'],
                            proc_info['cpu_percent'] or 0.0,
                            proc_info['memory_percent'] or 0.0,
                            proc_info['status'],
                            proc_info['num_threads'],
                            create_time,
                            proc_info['exe'] or ""
                        ))
                    except:
                        pass
                
                # 发送信号更新UI
                self.update_signal.emit(processes)
            except Exception as e:
                print(f"进程更新线程错误: {e}")
            
            # 暂停1秒
            time.sleep(1)
    
    def stop(self):
        """停止线程"""
        self.running = False
        self.wait()

class ChartWidget(QWidget):
    """自定义图表控件"""
    def __init__(self, parent=None, color=QColor(61, 174, 233)):
        super().__init__(parent)
        self.setMinimumHeight(150)
        self.data = []
        self.color = color
        self.max_value = 100
        self.title = ""
        
        # 设置背景色为深色
        self.setAutoFillBackground(True)
        palette = self.palette()
        palette.setColor(self.backgroundRole(), QColor(30, 30, 30))
        self.setPalette(palette)
    
    def set_data(self, data):
        self.data = data
        self.update()
    
    def set_title(self, title):
        self.title = title
        self.update()
    
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        
        rect = self.rect()
        margin = 40
        plot_rect = QRectF(
            margin,
            margin,
            rect.width() - 2 * margin,
            rect.height() - 2 * margin
        )
        
        # 绘制标题
        painter.setPen(QColor(200, 200, 200))
        font = QFont()
        font.setBold(True)
        painter.setFont(font)
        painter.drawText(rect, Qt.AlignTop | Qt.AlignHCenter, self.title)
        
        # 绘制坐标轴
        painter.setPen(QColor(100, 100, 100))
        painter.drawLine(
            plot_rect.bottomLeft(),
            plot_rect.topLeft()
        )
        painter.drawLine(
            plot_rect.bottomLeft(),
            plot_rect.bottomRight()
        )
        
        # 绘制网格线和刻度
        for i in range(0, 101, 20):
            y = plot_rect.bottom() - (i / self.max_value) * plot_rect.height()
            # 网格线
            painter.setPen(QColor(50, 50, 50))
            painter.drawLine(
                plot_rect.left(),
                y,
                plot_rect.right(),
                y
            )
            # 刻度文本
            painter.setPen(QColor(150, 150, 150))
            painter.drawText(
                0,
                y - 10,
                margin - 5,
                20,
                Qt.AlignRight | Qt.AlignVCenter,
                f"{i}%"
            )
        
        # 绘制数据曲线
        if len(self.data) > 1:
            path = QPainterPath()
            step_x = plot_rect.width() / (len(self.data) - 1)
            
            # 开始点
            x = plot_rect.left()
            y = plot_rect.bottom() - (self.data[0] / self.max_value) * plot_rect.height()
            path.moveTo(x, y)
            
            # 绘制曲线
            for i in range(1, len(self.data)):
                x = plot_rect.left() + i * step_x
                y = plot_rect.bottom() - (self.data[i] / self.max_value) * plot_rect.height()
                path.lineTo(x, y)
            
            # 填充区域
            fill_path = QPainterPath(path)
            fill_path.lineTo(plot_rect.bottomRight())
            fill_path.lineTo(plot_rect.bottomLeft())
            fill_path.closeSubpath()
            
            # 创建渐变填充
            gradient = QLinearGradient(plot_rect.topLeft(), plot_rect.bottomLeft())
            gradient.setColorAt(0, QColor(self.color.red(), self.color.green(), self.color.blue(), 100))
            gradient.setColorAt(1, QColor(self.color.red(), self.color.green(), self.color.blue(), 10))
            
            painter.fillPath(fill_path, gradient)
            
            # 绘制曲线
            painter.setPen(QPen(self.color, 2))
            painter.drawPath(path)
            
            # 绘制当前值
            if self.data:
                current_value = self.data[-1]
                painter.setPen(self.color)
                painter.drawText(
                    plot_rect.right() - 50,
                    plot_rect.top() - 5,
                    f"{current_value:.1f}%"
                )

class ProcessManager(QMainWindow):
    """进程管理器主窗口"""
    def __init__(self):
        super().__init__()
        self.setWindowTitle("进程管理器")
        self.setGeometry(100, 100, 1200, 700)
        
        # 设置主题样式
        self.setStyleSheet("""
            QMainWindow {background-color: #1E1E1E;}
            QTabWidget::pane {border: 1px solid #3E3E3E; background-color: #252526;}
            QTabBar::tab {background-color: #2D2D30; color: #CCCCCC; padding: 10px 20px; border: 1px solid #3E3E3E;}
            QTabBar::tab:selected {background-color: #252526; color: #FFFFFF; border-bottom-color: #252526;}
            QLabel {color: #CCCCCC;}
            QPushButton {background-color: #0E639C; color: white; border: none; padding: 8px 16px; border-radius: 4px;}
            QPushButton:hover {background-color: #1177BB;}
            QPushButton:pressed {background-color: #0D5A8C;}
            QPushButton#unban_button {background-color: #27AE60;}
            QPushButton#unban_button:hover {background-color: #2ECC71;}
            QPushButton#ban_button {background-color: #E74C3C;}
            QPushButton#ban_button:hover {background-color: #C0392B;}
            QLineEdit {background-color: #3C3C3C; color: #CCCCCC; border: 1px solid #3E3E3E; padding: 5px;}
            QTreeView {background-color: #1E1E1E; color: #CCCCCC; border: 1px solid #3E3E3E;}
            QTreeView::item {padding: 5px;}
            QTreeView::item:selected {background-color: #264F78;}
            QStatusBar {background-color: #252526; color: #CCCCCC;}
            QHeaderView::section {background-color: #3C3C3C; color: #CCCCCC; padding: 8px; border: 1px solid #3E3E3E;}
        """)
        
        # 初始化数据库
        self.init_database()
        
        # 创建中央部件
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.main_layout = QVBoxLayout(self.central_widget)
        
        # 创建标签页
        self.tabs = QTabWidget()
        self.tabs.setTabsClosable(False)
        self.main_layout.addWidget(self.tabs)
        
        # 创建各个标签页
        self.process_tab = QWidget()
        self.performance_tab = QWidget()
        self.apps_tab = QWidget()
        self.services_tab = QWidget()
        self.banned_tab = QWidget()
        
        # 添加标签页
        self.tabs.addTab(self.process_tab, "进程")
        self.tabs.addTab(self.performance_tab, "性能")
        self.tabs.addTab(self.apps_tab, "应用")
        self.tabs.addTab(self.services_tab, "服务")
        self.tabs.addTab(self.banned_tab, "封禁")
        
        # 初始化标签页
        self.init_process_tab()
        self.init_performance_tab()
        self.init_apps_tab()
        self.init_services_tab()
        self.init_banned_tab()
        
        # 创建状态栏
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        self.status_label = QLabel("就绪")
        self.status_bar.addWidget(self.status_label)
        
        # 创建性能监控线程
        self.perf_thread = PerformanceMonitorThread(self)
        self.perf_thread.update_cpu_signal.connect(self.update_cpu_data)
        self.perf_thread.update_memory_signal.connect(self.update_memory_data)
        self.perf_thread.start()
        
        # 创建进程更新线程
        self.process_thread = ProcessUpdaterThread(self)
        self.process_thread.update_signal.connect(self.update_process_table)
        self.process_thread.start()
        
        # 初始化排序
        self.sort_column = -1
        self.sort_order = Qt.AscendingOrder
        
        # 显示初始数据
        self.update_process_table([])
        self.update_applications()
        self.update_services()
        self.update_banned_processes()
    
    def init_process_tab(self):
        """初始化进程标签页"""
        layout = QVBoxLayout(self.process_tab)
        
        # 顶部控制栏
        control_layout = QHBoxLayout()
        
        # 刷新按钮
        self.refresh_button = QPushButton("刷新")
        self.refresh_button.clicked.connect(self.refresh_processes)
        control_layout.addWidget(self.refresh_button)
        
        # 结束任务按钮
        self.end_task_button = QPushButton("结束任务")
        self.end_task_button.clicked.connect(self.end_selected_processes)
        control_layout.addWidget(self.end_task_button)
        
        # 封禁按钮
        self.ban_task_button = QPushButton("封禁选中进程")
        self.ban_task_button.clicked.connect(self.ban_selected_processes)
        control_layout.addWidget(self.ban_task_button)
        
        # 资源使用情况显示
        resource_layout = QHBoxLayout()
        self.cpu_label = QLabel("CPU: --%")
        self.memory_label = QLabel("内存: --%")
        resource_layout.addWidget(self.cpu_label)
        resource_layout.addSpacing(20)
        resource_layout.addWidget(self.memory_label)
        control_layout.addLayout(resource_layout)
        control_layout.addStretch()
        
        # 搜索框
        search_layout = QHBoxLayout()
        search_label = QLabel("搜索:")
        self.search_edit = QLineEdit()
        self.search_edit.setPlaceholderText("输入进程名或PID")
        self.search_edit.textChanged.connect(self.filter_processes)
        search_layout.addWidget(search_label)
        search_layout.addWidget(self.search_edit)
        
        # 进程表格
        self.process_model = QStandardItemModel(0, 8)
        headers = ["PID", "名称", "CPU (%)", "内存 (%)", "状态", "线程数", "创建时间", "路径"]
        self.process_model.setHorizontalHeaderLabels(headers)
        
        self.process_view = QTreeView()
        self.process_view.setModel(self.process_model)
        self.process_view.setSortingEnabled(True)
        self.process_view.setSelectionMode(QTreeView.ExtendedSelection)
        self.process_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.process_view.customContextMenuRequested.connect(self.show_process_context_menu)
        self.process_view.doubleClicked.connect(self.show_process_details)
        
        # 设置列宽
        self.process_view.header().resizeSection(0, 80)
        self.process_view.header().resizeSection(1, 180)
        self.process_view.header().resizeSection(2, 80)
        self.process_view.header().resizeSection(3, 80)
        self.process_view.header().resizeSection(4, 80)
        self.process_view.header().resizeSection(5, 80)
        self.process_view.header().resizeSection(6, 150)
        self.process_view.header().setSectionResizeMode(7, QHeaderView.Stretch)
        
        # 连接排序信号
        self.process_view.header().sortIndicatorChanged.connect(self.on_header_sort)
        
        # 添加到布局
        layout.addLayout(control_layout)
        layout.addLayout(search_layout)
        layout.addWidget(self.process_view)
    
    def init_performance_tab(self):
        """初始化性能标签页"""
        # 使用QSplitter进行布局，允许用户调整各部分大小
        main_splitter = QSplitter(Qt.Vertical)
        layout = QVBoxLayout(self.performance_tab)
        layout.addWidget(main_splitter)
        
        # CPU性能部分
        cpu_widget = QWidget()
        cpu_layout = QVBoxLayout(cpu_widget)
        
        # CPU图表
        self.cpu_chart = ChartWidget(color=QColor(46, 204, 113))
        self.cpu_chart.set_title("CPU 使用率")
        cpu_layout.addWidget(self.cpu_chart)
        
        # CPU信息标签
        self.cpu_info_label = QLabel("CPU信息加载中...")
        cpu_layout.addWidget(self.cpu_info_label)
        
        # 内存性能部分
        memory_widget = QWidget()
        memory_layout = QVBoxLayout(memory_widget)
        
        # 内存图表
        self.memory_chart = ChartWidget(color=QColor(52, 152, 219))
        self.memory_chart.set_title("内存 使用率")
        memory_layout.addWidget(self.memory_chart)
        
        # 内存信息标签
        self.memory_info_label = QLabel("内存信息加载中...")
        memory_layout.addWidget(self.memory_info_label)
        
        # 系统信息部分
        system_widget = QWidget()
        system_layout = QVBoxLayout(system_widget)
        
        system_title = QLabel("系统信息")
        font = QFont()
        font.setBold(True)
        font.setPointSize(12)
        system_title.setFont(font)
        system_layout.addWidget(system_title)
        
        self.system_info_text = QTextEdit()
        self.system_info_text.setReadOnly(True)
        self.system_info_text.setMinimumHeight(200)
        self.system_info_text.setStyleSheet("""
            QTextEdit {background-color: #1E1E1E; color: #CCCCCC; border: 1px solid #3E3E3E; padding: 10px;}
        """)
        
        # 填充系统信息
        self.system_info_text.setPlainText(self.get_system_info())
        system_layout.addWidget(self.system_info_text)
        
        # 添加到splitter
        main_splitter.addWidget(cpu_widget)
        main_splitter.addWidget(memory_widget)
        main_splitter.addWidget(system_widget)
        
        # 设置初始大小比例
        main_splitter.setSizes([200, 200, 300])
    
    def init_apps_tab(self):
        """初始化应用标签页"""
        layout = QVBoxLayout(self.apps_tab)
        
        # 刷新按钮
        self.refresh_apps_button = QPushButton("刷新应用列表")
        self.refresh_apps_button.clicked.connect(self.update_applications)
        layout.addWidget(self.refresh_apps_button)
        
        # 应用列表
        self.apps_model = QStandardItemModel(0, 2)
        self.apps_model.setHorizontalHeaderLabels(["应用名称", "PID"])
        
        self.apps_view = QTreeView()
        self.apps_view.setModel(self.apps_model)
        self.apps_view.header().resizeSection(0, 400)
        self.apps_view.header().resizeSection(1, 80)
        
        layout.addWidget(self.apps_view)
    
    def init_services_tab(self):
        """初始化服务标签页"""
        layout = QVBoxLayout(self.services_tab)
        
        # 服务列表
        self.services_model = QStandardItemModel(0, 4)
        self.services_model.setHorizontalHeaderLabels(["名称", "显示名称", "状态", "PID"])
        
        self.services_view = QTreeView()
        self.services_view.setModel(self.services_model)
        self.services_view.header().resizeSection(0, 150)
        self.services_view.header().resizeSection(1, 300)
        self.services_view.header().resizeSection(2, 100)
        self.services_view.header().resizeSection(3, 80)
        
        layout.addWidget(self.services_view)
    
    def init_banned_tab(self):
        """初始化封禁标签页"""
        layout = QVBoxLayout(self.banned_tab)
        
        # 顶部控制栏
        control_layout = QHBoxLayout()
        
        # 刷新按钮
        self.refresh_banned_button = QPushButton("刷新列表")
        self.refresh_banned_button.clicked.connect(self.update_banned_processes)
        control_layout.addWidget(self.refresh_banned_button)
        
        # 解封按钮
        self.unban_selected_button = QPushButton("解封选中")
        self.unban_selected_button.setObjectName("unban_button")
        self.unban_selected_button.clicked.connect(self.unban_selected_processes)
        control_layout.addWidget(self.unban_selected_button)
        
        control_layout.addStretch()
        layout.addLayout(control_layout)
        
        # 封禁进程列表
        self.banned_model = QStandardItemModel(0, 4)
        self.banned_model.setHorizontalHeaderLabels(["进程名称", "添加时间", "拦截次数", "操作"])
        
        self.banned_view = QTreeView()
        self.banned_view.setModel(self.banned_model)
        self.banned_view.header().resizeSection(0, 200)
        self.banned_view.header().resizeSection(1, 150)
        self.banned_view.header().resizeSection(2, 100)
        self.banned_view.header().resizeSection(3, 80)
        self.banned_view.setContextMenuPolicy(Qt.CustomContextMenu)
        
        # 添加拦截次数标签
        self.block_count_label = QLabel("拦截次数: 0")
        self.block_count_label.setStyleSheet("font-weight: bold; margin-top: 10px;")
        self.block_count_label.setAlignment(Qt.AlignCenter)
        self.banned_view.customContextMenuRequested.connect(self.show_banned_context_menu)
        
        layout.addWidget(self.banned_view)
        layout.addWidget(self.block_count_label)
    
    def get_system_info(self):
        """获取系统信息"""
        info = []
        info.append(f"操作系统: {platform.system()} {platform.release()} {platform.version()}")
        info.append(f"处理器: {platform.processor()}")
        info.append(f"系统架构: {platform.architecture()}")
        info.append(f"主机名: {platform.node()}")
        
        # CPU信息
        cpu_count = psutil.cpu_count(logical=True)
        cpu_physical = psutil.cpu_count(logical=False)
        info.append(f"\nCPU核心数: {cpu_physical} 物理核心, {cpu_count} 逻辑核心")
        
        # 内存信息
        memory = psutil.virtual_memory()
        total_memory = memory.total / (1024**3)
        available_memory = memory.available / (1024**3)
        info.append(f"\n总内存: {total_memory:.2f} GB")
        info.append(f"可用内存: {available_memory:.2f} GB")
        
        # 磁盘信息
        disks = psutil.disk_partitions()
        info.append("\n磁盘信息:")
        for disk in disks:
            try:
                disk_usage = psutil.disk_usage(disk.mountpoint)
                total = disk_usage.total / (1024**3)
                free = disk_usage.free / (1024**3)
                info.append(f"  {disk.mountpoint} ({disk.fstype}):")
                info.append(f"    总容量: {total:.2f} GB")
                info.append(f"    可用空间: {free:.2f} GB")
            except:
                info.append(f"  {disk.mountpoint} ({disk.fstype}): 无法获取信息")
        
        return "\n".join(info)
    
    def update_process_table(self, processes):
        """更新进程表格数据"""
        # 保存当前选择的PID - 改进版本，从每一行获取第一个单元格(PID)
        selected_pids = set()
        if self.process_view.selectionModel():
            # 获取所有选中的行
            selected_rows = set()
            for index in self.process_view.selectionModel().selectedIndexes():
                selected_rows.add(index.row())
            
            # 从每一行获取PID
            for row in selected_rows:
                pid_index = self.process_model.index(row, 0)
                if pid_index.isValid():
                    try:
                        selected_pids.add(int(pid_index.data()))
                    except:
                        pass
        
        # 清空表格
        self.process_model.setRowCount(0)
        
        # 过滤进程
        search_text = self.search_edit.text().lower()
        filtered_processes = []
        
        for proc in processes:
            pid, name, cpu_percent, memory_percent, status, threads, create_time, path = proc
            
            # 搜索过滤
            if search_text and not (search_text in str(name).lower() or search_text in str(pid)):
                continue
                
            filtered_processes.append(proc)
        
        # 排序
        if self.sort_column >= 0:
            # 按照保存的排序方式排序
            filtered_processes.sort(
                key=lambda x: x[self.sort_column],
                reverse=(self.sort_order == Qt.DescendingOrder)
            )
        
        # 添加到表格
        for proc in filtered_processes:
            pid, name, cpu_percent, memory_percent, status, threads, create_time, path = proc
            
            # 创建行项
            items = [
                QStandardItem(str(pid)),
                QStandardItem(str(name)),
                QStandardItem(f"{cpu_percent:.1f}"),
                QStandardItem(f"{memory_percent:.1f}"),
                QStandardItem(str(status)),
                QStandardItem(str(threads)),
                QStandardItem(str(create_time)),
                QStandardItem(str(path))
            ]
            
            # 设置文本对齐
            for item in items[2:7]:  # CPU, 内存, 状态, 线程数, 创建时间
                item.setTextAlignment(Qt.AlignCenter)
            
            # 设置不可编辑
            for item in items:
                item.setEditable(False)
            
            # 添加行
            self.process_model.appendRow(items)
        
        # 恢复选择 - 改进版本，使用选择模型的批量选择
        if selected_pids and self.process_view.selectionModel():
            # 先清除当前选择
            self.process_view.selectionModel().clearSelection()
            
            # 收集所有要选中的索引
            indices_to_select = []
            for row in range(self.process_model.rowCount()):
                pid_item = self.process_model.item(row, 0)
                if pid_item:
                    try:
                        if int(pid_item.text()) in selected_pids:
                            # 选择整行
                            for col in range(self.process_model.columnCount()):
                                index = self.process_model.index(row, col)
                                indices_to_select.append(index)
                    except:
                        pass
            
            # 批量选择所有匹配的行
            for index in indices_to_select:
                self.process_view.selectionModel().select(index, QItemSelectionModel.Select | QItemSelectionModel.Rows)
        
        # 更新状态
        self.status_label.setText(f"就绪 - {len(filtered_processes)} 个进程")
    
    def update_cpu_data(self, cpu_percent, cpu_history):
        """更新CPU数据"""
        self.cpu_label.setText(f"CPU: {cpu_percent:.1f}%")
        self.cpu_chart.set_data(cpu_history)
        
        # 更新CPU信息
        try:
            cpu_freq = psutil.cpu_freq()
            if cpu_freq:
                cpu_info = f"CPU: {psutil.cpu_count(logical=True)} 核心 @ {cpu_freq.current:.2f} MHz (最高: {cpu_freq.max:.2f} MHz) - 使用率: {cpu_percent:.1f}%"
            else:
                cpu_info = f"CPU: {psutil.cpu_count(logical=True)} 核心 - 使用率: {cpu_percent:.1f}%"
            self.cpu_info_label.setText(cpu_info)
        except:
            self.cpu_info_label.setText(f"CPU使用率: {cpu_percent:.1f}%")
    
    def update_memory_data(self, memory_percent, total_gb, used_gb, memory_history):
        """更新内存数据"""
        self.memory_label.setText(f"内存: {memory_percent:.1f}%")
        self.memory_chart.set_data(memory_history)
        
        # 更新内存信息
        self.memory_info_label.setText(
            f"总内存: {total_gb:.2f} GB | 已用: {used_gb:.2f} GB ({memory_percent:.1f}%)"
        )
    
    def update_applications(self):
        """更新应用列表"""
        self.apps_model.setRowCount(0)
        
        if WIN32_AVAILABLE:
            # 使用win32api获取窗口
            windows = []
            
            def enum_windows_callback(hwnd, results):
                if win32gui.IsWindowVisible(hwnd):
                    title = win32gui.GetWindowText(hwnd)
                    if title and len(title.strip()) > 0:
                        try:
                            _, pid = win32process.GetWindowThreadProcessId(hwnd)
                            results.append((title, pid))
                        except:
                            results.append((title, "-"))
            
            win32gui.EnumWindows(enum_windows_callback, windows)
            
            # 去重
            seen_titles = set()
            for title, pid in windows:
                if title not in seen_titles:
                    seen_titles.add(title)
                    items = [
                        QStandardItem(title),
                        QStandardItem(str(pid))
                    ]
                    for item in items:
                        item.setEditable(False)
                    items[1].setTextAlignment(Qt.AlignCenter)
                    self.apps_model.appendRow(items)
        else:
            # 退回到使用psutil
            for proc in psutil.process_iter(['pid', 'name']):
                try:
                    proc_info = proc.info
                    items = [
                        QStandardItem(proc_info['name']),
                        QStandardItem(str(proc_info['pid']))
                    ]
                    for item in items:
                        item.setEditable(False)
                    items[1].setTextAlignment(Qt.AlignCenter)
                    self.apps_model.appendRow(items)
                except:
                    pass
    
    def update_services(self):
        """更新服务列表"""
        self.services_model.setRowCount(0)
        
        # 简化版本，使用进程作为服务
        for proc in psutil.process_iter(['pid', 'name']):
            try:
                proc_info = proc.info
                items = [
                    QStandardItem(proc_info['name']),
                    QStandardItem(proc_info['name']),
                    QStandardItem("运行中"),
                    QStandardItem(str(proc_info['pid']))
                ]
                for item in items:
                    item.setEditable(False)
                items[2].setTextAlignment(Qt.AlignCenter)
                items[3].setTextAlignment(Qt.AlignCenter)
                self.services_model.appendRow(items)
            except:
                pass
    
    def on_header_sort(self, logical_index, order):
        """处理表格排序"""
        self.sort_column = logical_index
        self.sort_order = order
        
        # 触发进程更新以应用排序
        if self.process_thread.running:
            # 立即获取并更新进程列表
            threading.Thread(target=self._update_processes_immediately, daemon=True).start()
    
    def _update_processes_immediately(self):
        """立即更新进程列表"""
        processes = []
        try:
            for proc in psutil.process_iter([
                'pid', 'name', 'cpu_percent', 'memory_percent', 
                'status', 'num_threads', 'create_time', 'exe'
            ]):
                try:
                    proc_info = proc.info
                    create_time = datetime.fromtimestamp(
                        proc_info['create_time']
                    ).strftime('%Y-%m-%d %H:%M:%S')
                    
                    processes.append((
                        proc_info['pid'],
                        proc_info['name'],
                        proc_info['cpu_percent'] or 0.0,
                        proc_info['memory_percent'] or 0.0,
                        proc_info['status'],
                        proc_info['num_threads'],
                        create_time,
                        proc_info['exe'] or ""
                    ))
                except:
                    pass
        except:
            pass
        
        # 在主线程更新UI
        QTimer.singleShot(0, lambda: self.update_process_table(processes))
    
    def filter_processes(self, text):
        """过滤进程"""
        # 立即更新以应用过滤
        if self.process_thread.running:
            threading.Thread(target=self._update_processes_immediately, daemon=True).start()
    
    def refresh_processes(self):
        """刷新进程列表"""
        self.status_label.setText("正在刷新...")
        threading.Thread(target=self._update_processes_immediately, daemon=True).start()
    
    def show_process_context_menu(self, position):
        """显示进程右键菜单"""
        index = self.process_view.indexAt(position)
        if index.isValid():
            # 选中右键点击的项
            self.process_view.setCurrentIndex(index)
            
            # 获取进程名称
            name_index = self.process_model.index(index.row(), 1)
            process_name = name_index.data()
            
            # 检查是否已封禁
            is_banned = False
            banned_processes = self.get_banned_processes()
            for banned_name, _ in banned_processes:
                if process_name.lower() == banned_name.lower():
                    is_banned = True
                    break
            
            menu = QMenu()
            
            # 结束任务菜单项
            end_task_action = QAction("结束任务")
            end_task_action.triggered.connect(self.end_selected_processes)
            menu.addAction(end_task_action)
            
            # 封禁/解封菜单项
            if is_banned:
                unban_action = QAction("解除封禁")
                unban_action.triggered.connect(lambda: self.unban_process(process_name))
                menu.addAction(unban_action)
            else:
                ban_action = QAction("封禁进程")
                ban_action.triggered.connect(lambda: self.ban_process(process_name))
                menu.addAction(ban_action)
            
            # 查看属性菜单项
            properties_action = QAction("属性")
            properties_action.triggered.connect(self.show_process_details)
            menu.addAction(properties_action)
            
            # 刷新菜单项
            refresh_action = QAction("刷新")
            refresh_action.triggered.connect(self.refresh_processes)
            menu.addAction(refresh_action)
            
            # 显示菜单
            menu.exec(self.process_view.viewport().mapToGlobal(position))
    
    def show_process_details(self):
        """显示进程详情对话框"""
        selected_indexes = self.process_view.selectionModel().selectedRows(0)
        if not selected_indexes:
            return
        
        # 获取PID
        pid_str = selected_indexes[0].data()
        try:
            pid = int(pid_str)
            process = psutil.Process(pid)
        except:
            QMessageBox.warning(self, "错误", f"无法获取进程 {pid_str} 的信息")
            return
        
        # 创建详情对话框
        dialog = QDialog(self)
        dialog.setWindowTitle(f"进程属性 - {process.name()}")
        dialog.resize(600, 400)
        layout = QVBoxLayout(dialog)
        
        # 创建滚动区域
        scroll_area = QScrollArea()
        scroll_content = QWidget()
        scroll_layout = QVBoxLayout(scroll_content)
        scroll_area.setWidget(scroll_content)
        scroll_area.setWidgetResizable(True)
        
        # 获取进程信息
        try:
            # 基本信息
            info_groups = [
                ("基本信息", [
                    ("进程名称:", process.name()),
                    ("PID:", str(process.pid)),
                    ("状态:", process.status()),
                ]),
                ("资源使用", [
                    ("CPU使用率:", f"{process.cpu_percent(interval=0.1):.1f}%"),
                    ("内存使用率:", f"{process.memory_percent():.1f}%"),
                    ("线程数:", str(len(process.threads()))),
                ]),
                ("详细信息", [])
            ]
            
            # 尝试获取更多信息
            try:
                username = process.username()
                info_groups[0][1].append(("用户名:", username))
            except:
                pass
            
            try:
                create_time = datetime.fromtimestamp(process.create_time()).strftime('%Y-%m-%d %H:%M:%S')
                info_groups[0][1].append(("创建时间:", create_time))
            except:
                pass
            
            try:
                exe = process.exe()
                info_groups[2][1].append(("可执行文件:", exe))
            except:
                pass
            
            try:
                cmdline = " ".join(process.cmdline())
                info_groups[2][1].append(("命令行:", cmdline))
            except:
                pass
            
            # 添加到对话框
            for group_title, items in info_groups:
                if items:
                    # 组标题
                    title_label = QLabel(group_title)
                    font = QFont()
                    font.setBold(True)
                    title_label.setFont(font)
                    scroll_layout.addWidget(title_label)
                    
                    # 信息项
                    for label_text, value in items:
                        row_widget = QWidget()
                        row_layout = QHBoxLayout(row_widget)
                        row_layout.setContentsMargins(5, 2, 5, 2)
                        
                        label = QLabel(label_text)
                        label.setStyleSheet("color: #AAAAAA;")
                        value_label = QLabel(value)
                        value_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
                        
                        row_layout.addWidget(label)
                        row_layout.addWidget(value_label)
                        row_layout.addStretch()
                        scroll_layout.addWidget(row_widget)
                    
                    scroll_layout.addSpacing(10)
        except Exception as e:
            error_label = QLabel(f"获取进程信息时出错: {str(e)}")
            error_label.setStyleSheet("color: #FF6B6B;")
            scroll_layout.addWidget(error_label)
        
        # 添加到对话框布局
        layout.addWidget(scroll_area)
        
        # 显示对话框
        dialog.exec()
    
    def ban_selected_processes(self):
        """封禁选中的进程"""
        selected_indexes = self.process_view.selectionModel().selectedRows(0)
        if not selected_indexes:
            QMessageBox.information(self, "提示", "请先选择要封禁的进程")
            return
        
        # 获取选中的进程名
        selected_names = []
        for index in selected_indexes:
            name_index = self.process_model.index(index.row(), 1)
            name = name_index.data()
            selected_names.append(name)
        
        # 去重
        selected_names = list(set(selected_names))
        
        # 检查是否已经被封禁
        existing_banned = self.get_banned_processes()
        existing_names = [name for name, _, _ in existing_banned]
        
        new_banned = [name for name in selected_names if name.lower() not in [n.lower() for n in existing_names]]
        already_banned = [name for name in selected_names if name.lower() in [n.lower() for n in existing_names]]
        
        # 确认对话框
        if len(new_banned) == 0:
            QMessageBox.information(self, "提示", "选中的进程已经在封禁列表中")
            return
        
        if len(new_banned) == 1:
            text = f"确定要封禁进程 '{new_banned[0]}' 吗？"
        else:
            text = f"确定要封禁选中的 {len(new_banned)} 个进程吗？"
        
        reply = QMessageBox.question(self, "确认", text, QMessageBox.Yes | QMessageBox.No)
        if reply != QMessageBox.Yes:
            return
        
        # 封禁进程
        banned_count = 0
        for process_name in new_banned:
            try:
                self.ban_process(process_name)
                banned_count += 1
            except Exception as e:
                print(f"封禁进程 {process_name} 失败: {e}")
        
        # 显示结果
        message = f"成功封禁 {banned_count} 个进程"
        if already_banned:
            message += f"\n注意：{len(already_banned)} 个进程已经在封禁列表中"
        QMessageBox.information(self, "成功", message)
        
        # 刷新封禁进程列表
        self.update_banned_processes()
    
    def end_selected_processes(self):
        """结束选中的进程"""
        selected_indexes = self.process_view.selectionModel().selectedRows(0)
        if not selected_indexes:
            QMessageBox.information(self, "提示", "请先选择要结束的进程")
            return
        
        # 确认对话框
        if len(selected_indexes) == 1:
            pid = selected_indexes[0].data()
            name_index = self.process_model.index(selected_indexes[0].row(), 1)
            name = name_index.data()
            result = QMessageBox.question(
                self,
                "确认结束进程",
                f"确定要结束进程 '{name}' (PID: {pid}) 吗？",
                QMessageBox.Yes | QMessageBox.No
            )
        else:
            result = QMessageBox.question(
                self,
                "确认结束进程",
                f"确定要结束选中的 {len(selected_indexes)} 个进程吗？",
                QMessageBox.Yes | QMessageBox.No
            )
        
        if result != QMessageBox.Yes:
            return
        
        # 结束进程
        success_count = 0
        failed_count = 0
        
        for index in selected_indexes:
            try:
                pid = int(index.data())
                process = psutil.Process(pid)
                
                # 尝试正常终止
                process.terminate()
                
                # 等待进程结束
                try:
                    process.wait(timeout=2)
                    success_count += 1
                except psutil.TimeoutExpired:
                    # 超时，尝试强制终止
                    try:
                        process.kill()
                        success_count += 1
                    except:
                        failed_count += 1
            except Exception as e:
                failed_count += 1
                print(f"结束进程失败: {e}")
        
        # 显示结果
        if failed_count == 0:
            QMessageBox.information(
                self,
                "操作完成",
                f"成功结束 {success_count} 个进程"
            )
        else:
            QMessageBox.warning(
                self,
                "操作结果",
                f"成功结束 {success_count} 个进程\n失败 {failed_count} 个进程"
            )
        
        # 刷新进程列表
        self.refresh_processes()
    
    def init_database(self):
        """初始化数据库"""
        try:
            # 确保数据库目录存在
            db_dir = os.path.dirname('./data.db')
            if db_dir and not os.path.exists(db_dir):
                os.makedirs(db_dir)
            
            # 连接数据库（主线程使用）
            self.db_path = './data.db'
            
            # 在主线程中创建表
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 创建封禁进程表
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS banned_processes (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    process_name TEXT NOT NULL UNIQUE,
                    add_time TEXT NOT NULL,
                    block_count INTEGER DEFAULT 0
                )
            ''')
            
            conn.commit()
            conn.close()
        except Exception as e:
            print(f"数据库初始化错误: {e}")
    
    def get_banned_processes(self):
        """获取所有封禁的进程"""
        try:
            # 为每个调用创建独立连接
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            cursor.execute('SELECT process_name, add_time, block_count FROM banned_processes')
            result = cursor.fetchall()
            conn.close()
            return result
        except Exception as e:
            print(f"获取封禁进程错误: {e}")
            return []
    
    def ban_process(self, process_name):
        """封禁指定进程"""
        try:
            # 为每个操作创建独立连接
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # 检查是否已存在
            cursor.execute('SELECT id FROM banned_processes WHERE process_name = ?', (process_name,))
            if cursor.fetchone():
                QMessageBox.information(self, "提示", f"进程 '{process_name}' 已在封禁列表中")
                conn.close()
                return
            
            # 添加到封禁列表
            current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            cursor.execute(
                'INSERT INTO banned_processes (process_name, add_time, block_count) VALUES (?, ?, ?)',
                (process_name, current_time, 0)
            )
            conn.commit()
            conn.close()
            
            QMessageBox.information(self, "成功", f"进程 '{process_name}' 已添加到封禁列表")
            self.update_banned_processes()
            
            # 立即终止当前运行的该进程
            for proc in psutil.process_iter(['pid', 'name']):
                try:
                    proc_info = proc.info
                    if proc_info['name'].lower() == process_name.lower():
                        proc.terminate()
                        try:
                            proc.wait(timeout=1)
                        except psutil.TimeoutExpired:
                            try:
                                proc.kill()
                            except:
                                pass
                except:
                    pass
            
            # 刷新进程列表
            self.refresh_processes()
        except Exception as e:
            print(f"封禁进程错误: {e}")
            QMessageBox.warning(self, "错误", f"封禁进程时出错: {str(e)}")
    
    def unban_process(self, process_name):
        """解除进程封禁"""
        try:
            # 为每个操作创建独立连接
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            cursor.execute('DELETE FROM banned_processes WHERE process_name = ?', (process_name,))
            conn.commit()
            affected_rows = cursor.rowcount
            conn.close()
            
            if affected_rows > 0:
            
                QMessageBox.information(self, "成功", f"进程 '{process_name}' 已解除封禁")
                self.update_banned_processes()
            else:
                QMessageBox.information(self, "提示", f"进程 '{process_name}' 不在封禁列表中")
        except Exception as e:
            print(f"解除封禁错误: {e}")
            QMessageBox.warning(self, "错误", f"解除封禁时出错: {str(e)}")
    
    def increment_block_count(self, process_name):
        """增加封禁进程的拦截次数"""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            cursor.execute(
                'UPDATE banned_processes SET block_count = block_count + 1 WHERE process_name = ?',
                (process_name,)
            )
            conn.commit()
            conn.close()
        except Exception as e:
            print(f"更新拦截次数错误: {e}")
    
    def update_banned_processes(self):
        """更新封禁进程列表"""
        self.banned_model.setRowCount(0)
        
        banned_processes = self.get_banned_processes()
        total_block_count = 0
        
        for process_name, add_time, block_count in banned_processes:
            total_block_count += block_count
            # 创建行项
            name_item = QStandardItem(process_name)
            time_item = QStandardItem(add_time)
            count_item = QStandardItem(str(block_count))
            
            # 设置不可编辑
            name_item.setEditable(False)
            time_item.setEditable(False)
            count_item.setEditable(False)
            time_item.setTextAlignment(Qt.AlignCenter)
            count_item.setTextAlignment(Qt.AlignCenter)
            
            # 添加行
            self.banned_model.appendRow([name_item, time_item, count_item, QStandardItem()])
            
            # 在每行末尾添加解封按钮
            row = self.banned_model.rowCount() - 1
            unban_button = QPushButton("解封")
            unban_button.setObjectName("unban_button")
            unban_button.clicked.connect(lambda checked, name=process_name: self.unban_process(name))
            self.banned_view.setIndexWidget(self.banned_model.index(row, 3), unban_button)
        
        # 更新总拦截次数标签
        if hasattr(self, 'block_count_label'):
            self.block_count_label.setText(f"拦截次数: {total_block_count}")
    
    def unban_selected_processes(self):
        """解封选中的进程"""
        selected_indexes = self.banned_view.selectionModel().selectedRows(0)
        if not selected_indexes:
            QMessageBox.information(self, "提示", "请先选择要解封的进程")
            return
        
        # 确认对话框
        if len(selected_indexes) == 1:
            name = selected_indexes[0].data()
            result = QMessageBox.question(
                self,
                "确认解封",
                f"确定要解除进程 '{name}' 的封禁吗？",
                QMessageBox.Yes | QMessageBox.No
            )
        else:
            result = QMessageBox.question(
                self,
                "确认解封",
                f"确定要解除选中的 {len(selected_indexes)} 个进程的封禁吗？",
                QMessageBox.Yes | QMessageBox.No
            )
        
        if result != QMessageBox.Yes:
            return
        
        # 解封进程
        success_count = 0
        
        # 为每个操作创建独立连接
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        
        for index in selected_indexes:
            process_name = index.data()
            try:
                cursor.execute('DELETE FROM banned_processes WHERE process_name = ?', (process_name,))
                if cursor.rowcount > 0:
                    success_count += 1
            except:
                pass
        
        conn.commit()
        conn.close()
        
        # 更新列表
        self.update_banned_processes()
        
        # 显示结果
        QMessageBox.information(
            self,
            "操作完成",
            f"成功解除 {success_count} 个进程的封禁"
        )
    
    def show_banned_context_menu(self, position):
        """显示封禁进程右键菜单"""
        index = self.banned_view.indexAt(position)
        if index.isValid():
            # 选中右键点击的项
            self.banned_view.setCurrentIndex(index)
            
            menu = QMenu()
            
            # 解除封禁菜单项
            unban_action = QAction("解除封禁")
            unban_action.triggered.connect(self.unban_selected_processes)
            menu.addAction(unban_action)
            
            # 刷新菜单项
            refresh_action = QAction("刷新")
            refresh_action.triggered.connect(self.update_banned_processes)
            menu.addAction(refresh_action)
            
            # 显示菜单
            menu.exec(self.banned_view.viewport().mapToGlobal(position))
    
    def closeEvent(self, event):
        """窗口关闭事件"""
        # 停止线程
        self.perf_thread.stop()
        self.process_thread.stop()
        
        # 接受关闭事件
        event.accept()

def main():
    """主函数"""
    # 创建应用
    app = QApplication(sys.argv)
    
    # 设置应用样式
    app.setStyle("Fusion")
    
    # 创建并显示主窗口
    window = ProcessManager()
    window.show()
    
    # 运行应用
    sys.exit(app.exec())

if __name__ == "__main__":
    main()